// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: qiang

#pragma once

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/mercado/api_util/auth_key.h"
#include "coin2/exchange/mercado/api_util/rate_tracker.h"
#include "coin2/exchange/mercado/symbology/product.h"
#include "coin2/exchange/order/mercado.pb.h"

class MercadoNativePrivateClient : public coin2::exchange::base::order::NativePrivateClient {
 public:
  using RestParams = coin2::exchange::order::MercadoSpotRestParams;
  using NativeClientConfig = coin2::exchange::order::OrderConnectionConfig;
  using ActionType = coin2::exchange::base::order::NativePrivateClient::ActionType;
  using MercadoRateTracker = coin2::exchange::mercado::api_util::MercadoRateTracker;
  using MercadoProduct = coin2::exchange::mercado::symbology::MercadoProduct;

 public:
  explicit MercadoNativePrivateClient(
      const MarketExchangeApi& mea,
      const NativeClientConfig& config);

  std::shared_ptr<AsioHttpContext> QueryAccountBalance();
  std::shared_ptr<AsioHttpContext> Accounts();
  std::shared_ptr<AsioHttpContext> QueryToken();

  std::shared_ptr<AsioHttpContext> ListOrder(const RestParams& params);

  RestParams GetRestOrderParams(const OrderSpec& order_spec, int64_t proc_order_id);
  RestParams GetRestCancelParams(const IOrderContext& order_context);
  std::shared_ptr<AsioHttpContext> PlaceOrder(const RestParams& params);
  std::shared_ptr<AsioHttpContext> CancelOrder(const RestParams& params);

  std::shared_ptr<AsioHttpContext> PlaceOrderNorm(const OrderExecution&) override;
  std::shared_ptr<AsioHttpContext> CancelOrderNorm(const OrderExecution&) override;

  std::shared_ptr<AsioHttpContext> SubmitOrderExecution(const OrderExecutionProto& order) override;
  std::shared_ptr<AsioHttpContext> SubmitRestQuery(const RestQueryProto& query) override;
  std::string DebugString() const;

  int64_t GetTokenExpiration() { return expiration_; }

  bool HasAccountId() { return account_id_.size() != 0; }

 private:
  void AccountCallBack(const std::string& channel, void* data);
  void TokenCallBack(const std::string& channel, void* data);
  std::string ToExchangeOrderId(const std::string& og_exchange_id);

 private:
  int64_t start_time_;
  std::unordered_map<std::string, int32_t> api_block_info_;
  std::unordered_map<std::string, int32_t> api_req_info_;
  MercadoRateTracker* local_rate_tracker_;

  int64_t expiration_{0};
  std::string account_id_;
};
